#include "UtilityPCH.h"

#include "UT_SamplerBase.h"
#include "UT_MathHelper.h"

using namespace Utility;

//---------------------------------------------------------------------
// UT_Sample
//---------------------------------------------------------------------
UT_Sample::UT_Sample(UT_SamplerBase* sampler, UT_IntegratorSurface *surf, UT_IntegratorVolume *vol, const UT_Scene *scene)
{
	//if (surf) surf->RequestSamples(sampler, this, scene);
	//if (vol)  vol->RequestSamples(sampler, this, scene);
	_allocateSampleMemory();
}
//---------------------------------------------------------------------
UT_Sample *UT_Sample::Duplicate(int count) const 
{
	UT_Sample *ret = MM_NEW UT_Sample[count];
	
	for (int i = 0; i < count; ++i)
	{
		ret[i].m_k1DNumVector = m_k1DNumVector;
		ret[i].m_k2DNumVector = m_k2DNumVector;
		ret[i]._allocateSampleMemory();
	}
	return ret;
}
//---------------------------------------------------------------------
void UT_Sample::_allocateSampleMemory()
{
	// Allocate storage for sample pointers
	int nPtrs = m_k1DNumVector.GetSize() + m_k2DNumVector.GetSize();
	if (!nPtrs)
	{
		m_pp1DData = m_pp2DData = NULL;
		return;
	}

	m_pp1DData = (float**)(MM_STAND_ALIGN_ALLOC(nPtrs * sizeof(float*)));
	m_pp2DData = m_pp1DData + m_k1DNumVector.GetSize();

	// Compute total number of sample values needed
	int totSamples = 0;
	for (uint32_t i = 0; i < m_k1DNumVector.GetSize(); ++i)
		totSamples += m_k1DNumVector.GetAt(i);
	for (uint32_t i = 0; i < m_k2DNumVector.GetSize(); ++i)
		totSamples += 2 * m_k2DNumVector.GetAt(i);

	// Allocate storage for sample values
	float *mem = (float*)(MM_STAND_ALIGN_ALLOC(totSamples * sizeof(float)));
	
	for (uint32_t i = 0; i < m_k1DNumVector.GetSize(); ++i)
	{
		m_pp1DData[i] = mem;
		mem += m_k1DNumVector.GetAt(i);
	}
	
	for (uint32_t i = 0; i < m_k2DNumVector.GetSize(); ++i)
	{
		m_pp2DData[i] = mem;
		mem += 2 * m_k2DNumVector.GetAt(i);
	}
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
// UT_SamplerBase
//---------------------------------------------------------------------
UT_SamplerBase::UT_SamplerBase(int32_t xstart, int32_t xend, 
	int32_t ystart, int32_t yend, int32_t spp, float sopen, float sclose)
	: m_iXPixelStart(xstart)
	, m_iXPixelEnd(xend)
	, m_iYPixelStart(ystart)
	, m_iYPixelEnd(yend)
	, m_iSamplesPerPixel(spp)
	, m_fShutterOpenTime(sopen)
	, m_fShutterCloseTime(sclose)
{

}
//---------------------------------------------------------------------
void UT_SamplerBase::_computeSubWindow(int num, int count, int *newXStart,
	int *newXEnd, int *newYStart, int *newYEnd) const 
{
	// Determine how many tiles to use in each dimension, _nx_ and _ny_
	int dx = m_iXPixelEnd - m_iXPixelStart, dy = m_iYPixelEnd - m_iYPixelStart;
	int nx = count, ny = 1;
	while ((nx & 0x1) == 0 && 2 * dx * ny < dy * nx)
	{
		nx >>= 1;
		ny <<= 1;
	}

	UT_ASSERT(nx * ny == count);

	// Compute $x$ and $y$ pixel sample range for sub-window
	int xo = num % nx, yo = num / nx;
	float tx0 = float(xo) / float(nx), tx1 = float(xo+1) / float(nx);
	float ty0 = float(yo) / float(ny), ty1 = float(yo+1) / float(ny);

	*newXStart = UT_MathHelper::Floor2Int(UT_MathHelper::Lerp(tx0, m_iXPixelStart, m_iXPixelEnd));
	*newXEnd   = UT_MathHelper::Floor2Int(UT_MathHelper::Lerp(tx1, m_iXPixelStart, m_iXPixelEnd));
	*newYStart = UT_MathHelper::Floor2Int(UT_MathHelper::Lerp(ty0, m_iYPixelStart, m_iYPixelEnd));
	*newYEnd   = UT_MathHelper::Floor2Int(UT_MathHelper::Lerp(ty1, m_iYPixelStart, m_iYPixelEnd));
}
//---------------------------------------------------------------------
//---------------------------------------------------------------------
//---------------------------------------------------------------------